<script setup>
import * as THREE from '../../../node_modules/three/src/Three.js'
import { OrbitControls } from '../../../node_modules/three/examples/jsm/controls/OrbitControls'
import Geometry from './index'
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'

const initConfig = reactive({
  scene: {}, // 三维对象
  camera: {}, // 相机对象
  renderer: '',
  controls: '',
  width: '',
  height: ''
})
/**
 * three对象 实例
 */
const scene = new THREE.Scene()
const textLoader = new THREE.TextureLoader()

//
const init = () => {
  //创建一个三维场景
  const depth = 8

  /**
   * 光学
   */

  // const minMaxGUIHelper = new THREE.minMaxGUIHelper(camera, 'near', 'far', 0.1)
  //设置相机方向
  //创建辅助坐标轴
  const axesHelper = new THREE.AxesHelper(200) //参数200标示坐标系大小，可以根据场景大小去设置
  scene.add(axesHelper)

  //创建一个WebGL渲染器
  initConfig.renderer = new THREE.WebGLRenderer()
  initConfig.renderer.setSize(initConfig.width, initConfig.height) //设置渲染区尺寸
  document.getElementById('my-three')?.appendChild(initConfig.renderer.domElement)
  initConfig.controls = new OrbitControls(initConfig.camera, initConfig.renderer.domElement) //创建控件对象
  // 转动惯性
  initConfig.controls.enableDamping = true
  // 禁止平移
  initConfig.controls.enablePan = false
  // 缩放限制
  // initConfig.controls.maxDistance = 12
  // 垂直旋转限制
  // initConfig.controls.minPolarAngle = Math.PI / 2
  // initConfig.controls.maxPolarAngle = Math.PI / 2
  initConfig.controls.addEventListener('change', () => {
    initConfig.renderer.render(scene, initConfig.camera) //监听鼠标，键盘事件
  })
}

// 相机初始化
const cameraInit = () => {
  initConfig.height = window.innerHeight
  initConfig.width = window.innerWidth
  //创建一个透视相机，窗口宽度，窗口高度
  initConfig.camera = new THREE.PerspectiveCamera(45, initConfig.width / initConfig.height, 1, 1000)
  //设置相机位置
  initConfig.camera.position.set(100, 100, 100)

  // scene.add(new THREE.CameraHelper(initConfig.camera))
}

onMounted(() => {
  cameraInit()
  init()
  // createTry()
  createSun()
  createSphere()
})

/**
 * 创建物体
 *
 */

const rooms = [
  {
    key: '1',
    position: {
      x: 1,
      y: 1,
      z: 1
    },
    map: 'https://cdn.polyhaven.com/asset_img/primary/abandoned_tiled_room.png?height=780'
  }
]
const createTry = () => {
  // 批量创建
  rooms.map(item => {
    const room = createRoom(item.key, item.position, item.map)
    return room
  })
}
const createRoom = (name, position, map) => {
  const geometry = new THREE.SphereGeometry(15, 256, 256)
  geometry.scale(1, 1, -1)
  const material = new THREE.MeshBasicMaterial({
    map: textLoader.load(map),
    side: THREE.DoubleSide
  })
  const room = new THREE.Mesh(geometry, material)
  room.name = name
  room.position.set(position.x, position.y, position.z)
  room.rotation.y = Math.PI / 2
  scene.add(room)
  return room
}

/**
 * 鼠标
 */
const onclick = event => {
  const wuti = new Geometry().onDocumentMouseDown(event, scene, initConfig.camera)
  // initConfig.camera.copy()
  const poin = wuti.position
  // console.log(poin)
  new Geometry().animateCamera(initConfig, poin)
}
// window.addEventListener('click', onclick, false)

// 页面缩放监听
window.addEventListener('resize', () => {
  initConfig.width = window.innerWidth
  initConfig.height = window.innerHeight
  // 更新渲染
  initConfig.renderer.setSize(initConfig.width, initConfig.height)
  initConfig.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  // 更新相机
  initConfig.camera.aspect = initConfig.width / initConfig.height
  initConfig.camera.updateProjectionMatrix()
})

/**
 * 星星
 */
let planet, satellite, ring
const stars = new THREE.Group()

// 太阳
// 要更新旋转角度的对象数组
let sunMesh,
  objects = []

const createSun = () => {
  const color = 0xffffff
  const intensity = 3
  const light = new THREE.PointLight(color, intensity)
  scene.add(light)

  // 一球多用
  const radius = 1
  const widthSegments = 6
  const heightSegments = 6
  const sphereGeometry = new THREE.SphereGeometry(radius, widthSegments, heightSegments)

  const sunMaterial = new THREE.MeshPhongMaterial({ emissive: 0xffff00 })
  sunMesh = new THREE.Mesh(sphereGeometry, sunMaterial)
  sunMesh.scale.set(5, 5, 5) // 扩大太阳的大小
  scene.add(sunMesh)
  objects.push(sunMesh)

  // 地球
  const earthMaterial = new THREE.MeshPhongMaterial({
    color: 0x2233ff,
    emissive: 0x112244
  })
  const earthMesh = new THREE.Mesh(sphereGeometry, earthMaterial)
  earthMesh.position.x = 10
  sunMesh.add(earthMesh)

  objects.push(earthMesh)
}
const createSphere = () => {
  // 创建星球
  const SphereMaterial = new THREE.MeshLambertMaterial({
    color: 0x03c03c,
    wireframe: true
  })
  const SphereGeometry = new THREE.SphereGeometry(5, 32, 32)
  planet = new THREE.Mesh(SphereGeometry, SphereMaterial)
  sunMesh.add(planet)

  // 创建星球轨道环
  const TorusGeometry = new THREE.TorusBufferGeometry(10, 5, 2, 120)
  const TorusMaterial = new THREE.MeshLambertMaterial({
    color: 0x40a9ff,
    wireframe: true
  })
  ring = new THREE.Mesh(TorusGeometry, TorusMaterial)
  ring.rotation.x = Math.PI / 2
  ring.rotation.y = -0.1 * (Math.PI / 2)
  sunMesh.add(ring)

  // 创建星星
  for (let i = 0; i < 150; i++) {
    const geometry = new THREE.IcosahedronGeometry(Math.random() * 2, 0)
    const material = new THREE.MeshToonMaterial({ color: 0xeeeeee })
    const mesh = new THREE.Mesh(geometry, material)
    mesh.position.x = (Math.random() - 0.5) * 700
    mesh.position.y = (Math.random() - 0.5) * 700
    mesh.position.z = (Math.random() - 0.5) * 700
    mesh.rotation.x = Math.random() * 2 * Math.PI
    mesh.rotation.y = Math.random() * 2 * Math.PI
    mesh.rotation.z = Math.random() * 2 * Math.PI
    stars.add(mesh)
  }
  scene.add(stars)
  tick()
}
// 动画
let time = 0.001
const axis = new THREE.Vector3(0, 0, 1)
const tick = () => {
  initConfig.controls && initConfig.controls.update()
  // TWEEN && TWEEN.update()
  initConfig.renderer.render(scene, initConfig.camera)
  time += 0.01

  objects.forEach(obj => {
    obj.rotation.y = time
    initConfig.camera.position.x = time * 5
  })
  const radian = (time * Math.PI) / 180
  // 星球位置动画
  // satellite && (satellite.rotation.y += 0.005)
  // 星球轨道环位置动画
  // satellite && satellite.rotateOnAxis(axis, Math.PI / 400)
  // 卫星位置动画
  planet.position.x = 40 * Math.sin(radian)
  // planet.position.y = 100 * Math.cos(radian)
  planet.position.z = 40 * Math.cos(radian)
  ring.position.x = 40 * Math.sin(radian)
  ring.position.y = 0 * Math.cos(radian)
  // initConfig.camera.position.x = -40 * Math.sin(radian)
  // initConfig.camera.position.y = -40 * Math.cos(radian)
  // initConfig.camera.position.z = 40 * Math.cos(radian)
  ring.position.z = 40 * Math.cos(radian)

  // 更新控制器
  initConfig.controls.update()
  window.requestAnimationFrame(tick)
}
</script>

<template>
  <div class="three" id="my-three"></div>
</template>
<style lang="scss" scoped>
.three {
  width: 100%;
  height: 600%;
}
</style>
